﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Build.Content;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public partial class ListView
{
    
    public void RefreshItems_Horizontal()
    {
        if (m_DataCount <= 0)
        {
            m_ItemPosAndSizeList.Clear();
            for (int i = 0; i < m_ItemNodeList.Count; ++i)
            {
                var itemNode = m_ItemNodeList[i];
                RecycleItem(itemNode.rtf);
            }
            m_ItemNodeList.Clear();
        }
        else
        {
            float viewportSize = this.ViewportSize_Vertical;
            var content = m_ScrollRect.content;
            float tmpItemTopDis = 0;
            for (int i = 0; i < m_DataCount; ++i)
            {
                var newItemRtf = m_OnObtainItem(this, i);
                if (null == newItemRtf)
                    break;
                newItemRtf.gameObject.SetActive(true);
                newItemRtf.SetParent(content, false);
                m_ItemNodeList.Add(new ItemNode(newItemRtf, i));
                if (0 == i)
                    tmpItemTopDis = ListViewUtil.GetItemNodeTopDis(newItemRtf);
                float itemSize = newItemRtf.rect.height;
                float itemBottomDis = tmpItemTopDis + itemSize;
                m_ItemPosAndSizeList.Add(new ItemPosAndSize(itemSize, itemBottomDis));
                Debug.Log($"tmpItemTop: {i}: bottomDis:{itemBottomDis}");
                if (tmpItemTopDis > viewportSize)
                    break;
                tmpItemTopDis = itemBottomDis + m_ItemSpace;
            }
            m_EndStub.SetAsLastSibling();

            for (int i = m_ItemNodeList.Count; i < m_DataCount; ++i)
            {
                tmpItemTopDis += m_ItemSpace;
                m_ItemPosAndSizeList.Add(new ItemPosAndSize(0, tmpItemTopDis));
            }

            if (m_ItemPosAndSizeList.Count != m_DataCount)
            {
                Debug.LogError($"cnt1: {m_ItemPosAndSizeList.Count}, cnt2:{m_DataCount}");
            }
        }
    }

    //offset: >0为往上, <0为往下
    private void ScrollToDataIndex_Horizontal(int itemIndex, float offset)
    {
        var itemPosAndSize = m_ItemPosAndSizeList[itemIndex];
        var content = m_ScrollRect.content;
        Vector2 lpos = content.localPosition;
        lpos.y = -itemPosAndSize.TopDis + offset;
        content.localPosition = lpos;
    }

    private int GetDataIndexByDis_Horizontal(float dis)
    {
        int cnt = m_ItemNodeList.Count;
        if (cnt == 0)
            return 0;
        float tmpBottomDis = m_ItemPosAndSizeList[0].bottomDis;
        if (dis <= tmpBottomDis)
            return 0;
        
        int endIndex = m_ItemPosAndSizeList.Count - 1;
        for (int i = 1; i <= endIndex; ++i)
        {
            tmpBottomDis = m_ItemPosAndSizeList[i].bottomDis;
            if (dis <= tmpBottomDis)
                return i;
        }

        return endIndex;
    }

    private float ViewportSize_Horizontal
    {
        get
        {
            var viewport = m_ScrollRect.viewport;
            float size = viewport.rect.height;
            return size;
        }
    }
    
    private float ScrollDistance_Horizontal
    {
        get
        {
            var content = m_ScrollRect.content;
            float dis = ListViewUtil.GetItemNodeTopDis(content);
            return dis;
        }
    }

    private void CheckAndRecycleTopItems_Horizontal(float scrollDis)
    {
        //顶部的回收
        int recycleItemNodeIndex = -1;
        for (int i = 0; i < m_ItemNodeList.Count; ++i)
        {
            var itemNode = m_ItemNodeList[i];
            var itemPosAndSize = m_ItemPosAndSizeList[itemNode.dataIndex];
            //float itemBottomDis = GetItemNodeTopDis(itemNode) + itemNode.rect.height; //条目bottom到content top的距离
            if (itemPosAndSize.bottomDis >= scrollDis)
            {
                //Debug.Log($"scroll up: check recycle: {i} -> {itemNode.name}, bottomDis: {itemBottomDis}, scrollDis:{scrollDis}");
                recycleItemNodeIndex = i - 2;
                break;
            }
        }

        float tmpBottomDis = 0;
        float tmpTopDis = 0;
        if (recycleItemNodeIndex >= 0)
        {
            m_LateUpdateFlag = 2;
            var itemNode = m_ItemNodeList[recycleItemNodeIndex];
            var itemPosAndSize = m_ItemPosAndSizeList[itemNode.dataIndex];
            tmpTopDis = itemPosAndSize.TopDis; //GetItemNodeTopDis(itemNode);
            tmpBottomDis = itemPosAndSize.bottomDis; //tmpTopDis + itemNode.rect.height;
                    
            for (int i = recycleItemNodeIndex; i >= 0; --i)
            {
                var tmpItemNode = m_ItemNodeList[i];
                m_ItemNodeList.RemoveAt(i);
                RecycleItem(tmpItemNode.rtf);
            }

            Debug.Log($"scroll up: {Time.frameCount}: recycleItemNodeIndex:{recycleItemNodeIndex}, {itemNode.rtf.name}, tmpBottomDis:{tmpBottomDis}");
            ListViewUtil.SetStubSize_Horizontal(m_BeginStub, tmpBottomDis);
        }
    }
    
    private void CheckAndFillBottomItems_Horizontal(float viewportBottomDis)
    {
        var listViewContent = m_ScrollRect.content;
        
        //底部不够的补充
        var lastItemNode = m_ItemNodeList[m_ItemNodeList.Count - 1];
        var lastItemPosAndSize = m_ItemPosAndSizeList[lastItemNode.dataIndex];
        float tmpTopDis = lastItemPosAndSize.TopDis; //GetItemNodeTopDis(itemNode_2);
        float tmpBottomDis = 0;
        
        float prevItemSize = lastItemPosAndSize.size; // itemNode_2.rect.height;
        int tmpItemIndex = lastItemNode.dataIndex; //GetItemIndexByDis(tmpTopDis);
        bool isAddNode = false;
        while (tmpTopDis <= viewportBottomDis)
        {
            tmpItemIndex++;
            if (tmpItemIndex >= m_DataCount)
                break;
                    
            var newItemRtf = m_OnObtainItem(this, tmpItemIndex);
            if (null == newItemRtf)
                break;
            isAddNode = true;
            newItemRtf.gameObject.SetActive(true);
            newItemRtf.SetParent(listViewContent, false);
            newItemRtf.SetAsLastSibling();
            m_ItemNodeList.Add(new ItemNode(newItemRtf, tmpItemIndex));

            tmpTopDis += prevItemSize;
            tmpTopDis += m_ItemSpace;
                    
            prevItemSize = newItemRtf.rect.height;
            tmpBottomDis = tmpTopDis + prevItemSize;
            m_ItemPosAndSizeList[tmpItemIndex] = new ItemPosAndSize(prevItemSize, tmpBottomDis); // tmpBottomDis;
            Debug.Log($"scrollUp: {Time.frameCount}: obtainItem: {tmpItemIndex}, {newItemRtf.name}, topDis:{tmpTopDis}, bottomDis:{tmpBottomDis}, lastItem.topDis:{lastItemNode.dataIndex}_{lastItemPosAndSize.TopDis}");
        }

        if (isAddNode)
        {
            m_LateUpdateFlag = 2;
            m_EndStub.SetAsLastSibling();
            float contentSize = m_ItemPosAndSizeList[m_ItemPosAndSizeList.Count - 1].bottomDis;
            ListViewUtil.SetStubSize_Horizontal(m_EndStub, contentSize - tmpBottomDis - m_ItemSpace);
        }
    }

    private void CheckAndRecycleBottomItems_Horizontal(float viewportBottomDis)
    {
        //底部的回收
        int recycleItemNodeIndex = -1;
        int endIndex = m_ItemNodeList.Count - 1;
        for (int i = endIndex; i >= 0; --i)
        {
            var itemNode = m_ItemNodeList[i];
            var itemPosAndSize = m_ItemPosAndSizeList[itemNode.dataIndex];
            float topDis = itemPosAndSize.TopDis; //GetItemNodeTopDis(itemNode);
            if (topDis <= viewportBottomDis)
            {
                //Debug.Log($"scrollDown: check recycle: {i} -> {itemNode.name}, topDis: {topDis}, vpBottomDis:{viewportBottomDis}");
                recycleItemNodeIndex = i + 2;
                break;
            }
        }

        float tmpTopDis = 0;
        if (recycleItemNodeIndex >= 0 && recycleItemNodeIndex <= endIndex)
        {
            m_LateUpdateFlag = 2;
            var itemNode = m_ItemNodeList[recycleItemNodeIndex];
            var itemPosAndSize = m_ItemPosAndSizeList[itemNode.dataIndex];
            tmpTopDis = itemPosAndSize.TopDis;// GetItemNodeTopDis(itemNode);
            for (int i = endIndex; i >= recycleItemNodeIndex; --i)
            {
                var tmpItemNode = m_ItemNodeList[i];
                m_ItemNodeList.RemoveAt(i);
                RecycleItem(tmpItemNode.rtf);
            }
                    
            //回收条目的空间得用占位节点填满
            Debug.Log($"scrollDown: {Time.frameCount}: recycleItemNodeIndex:{recycleItemNodeIndex}, {itemNode.rtf.name}, tmpTopDis:{tmpTopDis}");
            float contentSize = m_ItemPosAndSizeList[m_ItemPosAndSizeList.Count - 1].bottomDis;
            ListViewUtil.SetStubSize_Horizontal(m_EndStub, contentSize - tmpTopDis);
        }
    }

    private void CheckAndFillTopItems_Horizontal(float scrollDis)
    {
        var listViewContent = m_ScrollRect.content;
        
        //顶部不够的补充
        var firstItemNode = m_ItemNodeList[0];
        var firstItemPosAndSize = m_ItemPosAndSizeList[firstItemNode.dataIndex];

        float prevItemSize = firstItemPosAndSize.size;
        float tmpTopDis = firstItemPosAndSize.TopDis;// GetItemNodeTopDis(itemNode_2);
        float tmpBottomDis = firstItemPosAndSize.bottomDis; //条目bottom与content top的距离
        int tmpItemIndex = firstItemNode.dataIndex; //GetItemIndexByDis(tmpBottomDis);
        bool isAddNode = false;
        while (tmpItemIndex > 0 && tmpBottomDis >= scrollDis) //第1个VisibleItem的top进入视口了
        {
            tmpItemIndex -= 1;
            var newItemRtf = m_OnObtainItem(this, tmpItemIndex);
            if (null == newItemRtf)
                break;
            isAddNode = true;
            newItemRtf.gameObject.SetActive(true);
            newItemRtf.SetParent(listViewContent, false);
            newItemRtf.SetAsFirstSibling();
            m_ItemNodeList.Insert(0, new ItemNode(newItemRtf, tmpItemIndex));

            tmpBottomDis -= prevItemSize;
            tmpBottomDis -= m_ItemSpace;
            
            prevItemSize = newItemRtf.rect.height;
            m_ItemPosAndSizeList[tmpItemIndex] = new ItemPosAndSize(prevItemSize, tmpBottomDis);
            Debug.Log($"scrollDown: {Time.frameCount}:  obtainItem: {tmpItemIndex}, bottomDis:{tmpBottomDis}");
            tmpTopDis = tmpBottomDis - prevItemSize;
        }

        if (isAddNode)
        {
            m_LateUpdateFlag = 2;
            if (tmpItemIndex <= 0)
            {
                ListViewUtil.SetStubSize_Horizontal(m_BeginStub, 0); //隐藏beginStub
            }
            else
            {
                m_BeginStub.SetAsFirstSibling();
                float newSize = tmpTopDis - m_ItemSpace;
                ListViewUtil.SetStubSize_Horizontal(m_BeginStub, newSize);
            }
        }
    }
    
    private void OnValueChanged_ScrollRect_Horizontal(Vector2 vec2)
    {
        //Debug.Log($"OnValueChanged_ScrollRect: {vec2.y}");

        int oldScrollPercent = m_ScrollPercent;

        var listViewContent = m_ScrollRect.content;
        Vector2 lPos = listViewContent.localPosition;
        float scrollDis = 0; //viewport的top到content top的距离
        //左, 下是(0, 0)
        int v = Mathf.RoundToInt(vec2.y * 100);
        m_ScrollPercent = 100 - v;
        scrollDis = lPos.y;

        int deltaScrollPercent = m_ScrollPercent - oldScrollPercent;
        if (deltaScrollPercent > 0) //往上滑动
        {
            float viewportSize = this.ViewportSize;
            float viewportBottomDis = scrollDis + viewportSize; //viewport bottom与content top的距离
            
            if (oldScrollPercent >= 0 && oldScrollPercent <= 100) //滑动前, 没有overScroll
            {
                CheckAndRecycleTopItems_Horizontal(scrollDis);
            }
            CheckAndFillBottomItems_Horizontal(viewportBottomDis);
        }
        else if (deltaScrollPercent < 0) //往下滑动
        {
            if (oldScrollPercent >= 0 && oldScrollPercent <= 100) //滑动前, 没有overScroll
            {
                float viewportSize = ViewportSize;
                float viewportBottomDis = scrollDis + viewportSize; //viewport bottom与content top的距离
                
                CheckAndRecycleBottomItems_Horizontal(viewportBottomDis);
            }
            CheckAndFillTopItems_Horizontal(scrollDis);
        }
        else
        { 
            //没变
        }
    }
    
    private void UpdateItemsPosAndSize_Horizontal()
    {
        int endIndex = m_ItemNodeList.Count - 1;
        if (endIndex < 0)
            return;

        bool isAnyItemNodeChanged = false;
        //先把ui上的同步下来
        foreach (var itemNode in m_ItemNodeList)
        {
            float itemSize = itemNode.rtf.rect.height;
            float itemBottomDis = ListViewUtil.GetItemNodeTopDis(itemNode.rtf) + itemSize;
            //Debug.Log($"LateUpate: idx:{itemNode.itemIndex}, name:{itemNode.rtf.name}, itemSize:{itemSize}, itemBottomDis:{itemTopDis+itemSize}");
            int itemIndex = itemNode.dataIndex;
            if (!isAnyItemNodeChanged)
            {
                var itemPosAndSize = m_ItemPosAndSizeList[itemIndex];
                float delta = itemSize - itemPosAndSize.size;
                if (Math.Abs(delta) >= 0.001)
                {
                    isAnyItemNodeChanged = true;
                    m_ItemPosAndSizeList[itemIndex] = new ItemPosAndSize(itemSize, itemBottomDis);
                }
                else
                {
                    delta = itemBottomDis - itemPosAndSize.bottomDis;
                    if (Math.Abs(delta) >= 0.001)
                    {
                        isAnyItemNodeChanged = true;
                        m_ItemPosAndSizeList[itemIndex] = new ItemPosAndSize(itemSize, itemBottomDis);
                    }
                }
            }
            else
            {
                m_ItemPosAndSizeList[itemIndex] = new ItemPosAndSize(itemSize, itemBottomDis);
            }
        }

        if (!isAnyItemNodeChanged)
        {
            Debug.Log($"UpdateItemsPosAndSize: no itemPosAndSize change");
            return;
        }

        var firstItemNode = m_ItemNodeList[0];
        int firstItemIndex = firstItemNode.dataIndex;
        var firstItemPosAndSize = m_ItemPosAndSizeList[firstItemIndex];
        if (firstItemIndex <= 0)
        {
            ListViewUtil.SetStubSize_Horizontal(m_BeginStub, 0);
        }
        else
        {
            float newSize = firstItemPosAndSize.TopDis - m_ItemSpace;
            ListViewUtil.SetStubSize_Horizontal(m_BeginStub, newSize);
        }

        //在更新后续的条目
        var lastItemNode = m_ItemNodeList[endIndex];
        var lastItemPosAndSize = m_ItemPosAndSizeList[lastItemNode.dataIndex];
        float tmpBottomDis = lastItemPosAndSize.bottomDis;
        for (int i = lastItemNode.dataIndex + 1; i < m_DataCount; ++i)
        {
            var itemPosAndSize = m_ItemPosAndSizeList[i];
            tmpBottomDis += m_ItemSpace;
            tmpBottomDis += itemPosAndSize.size;
            itemPosAndSize.bottomDis = tmpBottomDis;
            m_ItemPosAndSizeList[i] = itemPosAndSize;
        }

        float contentSize = tmpBottomDis;
        ListViewUtil.SetStubSize_Horizontal(m_EndStub, contentSize - (lastItemPosAndSize.bottomDis + m_ItemSpace));
    }
    
}
